//
//  KLClient.m
//  WebRTCDemo_iOS
//
//  Created by szblsx2 on 2020/3/5.
//  Copyright © 2020 szblsx2. All rights reserved.
//

#import "KLClient.h"
#import "KLWebSocket.h"
#import "KLTool.h"

@interface KLClient ()
//KLWebSocket对象
@property (nonatomic, strong) KLWebSocket *mKLWebSocket;
//临时变量(发送推流时的请求id)
@property (nonatomic, assign) NSInteger temppublishId;

@end

@implementation KLClient

/**连接scoket*/
- (void)startWithServerUrl:(NSString *)sevrerUrl success:(void(^)(BOOL))success
{
    //先关闭
    [self.mKLWebSocket closeWebSocket];
    //再连接
    [self.mKLWebSocket connectWebSocketWithUrlString:sevrerUrl];
    //处理事件
    [self handleDataRecvice];
    //事件回调
    [self eventHandleComplete:^(BOOL status) {
        if (success) {
            success(status);
        }
    }];
}

/**断开连接*/
- (void)close
{
    [self.mKLWebSocket closeWebSocket];
}
#pragma mark - 发送信令
/**加入房间*/
- (void)sendJoin:(NSString *)rid info:(NSDictionary *)info
{
    NSDictionary *dic = @{ @"request": @(true),
                           @"id":@([KLTool toRandomId]),
                           @"method":@"join",
                           @"data":@{@"rid":rid,
                                     @"uid":kDeviceUUID,
                                     @"info":info}};
    NSLog(@"加入房间: %@",[KLTool dictToJson:dic]);
    [_mKLWebSocket sendData:[KLTool dictToJson:dic]];
}

/**离开房间*/
- (void)sendLeave:(NSString *)rid
{
    NSDictionary *dic = @{@"request":@(true),
                          @"id":@([KLTool toRandomId]),
                          @"method":@"leave",
                          @"data":@{@"rid":rid,@"uid":kDeviceUUID}};
    NSLog(@"离开房间 : %@",[KLTool dictToJson:dic]);
    [_mKLWebSocket sendData:[KLTool dictToJson:dic]];
}

/**发布流*/
- (void)sendPublish:(NSString *)rid sdp:(NSString *)sdp bScreen:(BOOL)bScreen
{
    _temppublishId = [KLTool toRandomId];
    NSDictionary *dic = @{@"request":@(true),
                          @"id":@(_temppublishId),
                          @"method":@"publish",
                          @"data":@{@"rid":rid,@"jsep":@{@"sdp":sdp,@"type":@"offer"},@"options":@{@"audio":@(true),@"video":@(true),@"screen":@(bScreen),@"codec":@"h264"}}};
    NSLog(@"发布流 : %@",[KLTool dictToJson:dic]);
    [_mKLWebSocket sendData:[KLTool dictToJson:dic]];
    //事件回调
    NSDictionary *responeDict = @{@"event":@(2003),@"code":@(200),@"mid":@"",@"roomId":rid};
    if (self.eventHandleBlock) {
        self.eventHandleBlock(responeDict);
    }
}

/**取消发布流*/
- (void)sendUnpublish:(NSString *)rid mid:(NSString *)mid
{
    NSDictionary *dic = @{@"request":@(true),
                          @"id":@([KLTool toRandomId]),
                          @"method":@"unpublish",
                          @"data":@{@"rid":rid,@"mid":mid}};
    NSLog(@"取消发布流 : %@",[KLTool dictToJson:dic]);
    [_mKLWebSocket sendData:[KLTool dictToJson:dic]];
    //事件回调
    NSDictionary *responeDict = @{@"event":@(2004),@"code":@(200),@"mid":mid,@"roomId":rid};
    if (self.eventHandleBlock) {
        self.eventHandleBlock(responeDict);
    }
}

/**订阅流*/
- (void)sendSubscribe:(NSString *)rid mid:(NSString *)mid sdp:(NSString *)sdp
{
    NSDictionary *dic = @{@"request":@(true),
                          @"id":@([KLTool toRandomId]),
                          @"method":@"subscribe",
                          @"data":@{@"rid":rid,@"jsep":@{@"sdp":sdp,@"type":@"offer"},@"mid":mid}};
    NSLog(@"订阅流 : %@",[KLTool dictToJson:dic]);
    [_mKLWebSocket sendData:[KLTool dictToJson:dic]];
    //事件回调
    NSDictionary *responeDict = @{@"event":@(2005),@"code":@(200),@"mid":mid,@"roomId":rid};
    if (self.eventHandleBlock) {
        self.eventHandleBlock(responeDict);
    }
}

/**取消订阅流*/
- (void)sendUnsubscribe:(NSString *)rid mid:(NSString *)mid
{
    NSDictionary *dic = @{@"request":@(true),
                          @"id":@([KLTool toRandomId]),
                          @"method":@"unsubscribe",
                          @"data":@{@"rid":rid,@"mid":mid}};
    NSLog(@"取消订阅流 : %@",[KLTool dictToJson:dic]);
    [_mKLWebSocket sendData:[KLTool dictToJson:dic]];
    //事件回调
    NSDictionary *responeDict = @{@"event":@(2006),@"code":@(200),@"mid":mid,@"roomId":rid};
    if (self.eventHandleBlock) {
        self.eventHandleBlock(responeDict);
    }
}

/**发送IceCandidate*/
- (void)sendIceCandidate:(NSString *)rid mid:(NSString *)mid object:(NSDictionary *)object bPub:(BOOL)bPub
{
    NSDictionary *dic = @{  @"request":@(true),
                            @"id":@([KLTool toRandomId]),
                            @"method":@"trickle",
                            @"data":@{@"rid":rid,@"mid":mid,@"candidate":object,@"isPub":@(bPub)}};
    if (bPub) {
        NSLog(@"推流发送IceCandidate : %@",[KLTool dictToJson:dic]);
    }else{
        NSLog(@"订阅发送IceCandidate : %@",[KLTool dictToJson:dic]);
    }
    [_mKLWebSocket sendData:[KLTool dictToJson:dic]];
    //事件回调
    NSDictionary *responeDict = @{@"event":@(2007),@"code":@(200),@"mid":mid,@"roomId":rid};
    if (self.eventHandleBlock) {
        self.eventHandleBlock(responeDict);
    }
}

#pragma mark - 接收信令

/**接收服务端信息*/
- (void)handleDataRecvice
{
    __weak __typeof(self) ws = self;
    self.mKLWebSocket.onDataRecvice = ^(NSString * _Nonnull message) {
        NSLog(@"收到服务端信息:%@",message);
        NSDictionary *result = [KLTool jsonToDict:message];
        if ([result.allKeys containsObject:@"response"]) {
            BOOL bResp = [result[@"response"] boolValue];
            if (bResp) {
                NSString *type = result[@"data"][@"jsep"][@"type"];
                if ([@"answer" isEqualToString:type]) {
                    NSDictionary *jsonObjDict = result[@"data"];
                    NSString *sdp = jsonObjDict[@"jsep"][@"sdp"] ?: @"";
                    NSString *mid = jsonObjDict[@"mid"] ?: @"";
                    // 根据temppublishId来判断是发布流的回应还是订阅流的回应 如果responseId和temppublishId相等 表示是发布流的响应
                    NSInteger responseId = [result[@"id"] integerValue];
                    if (responseId == self.temppublishId) {
                        if (ws.delegate && [ws.delegate respondsToSelector:@selector(klClient:respPublishWithMid:answerSdp:)]) {
                            [ws.delegate klClient:ws respPublishWithMid:mid answerSdp:sdp];
                        }
                    }else{
                        if (ws.delegate && [ws.delegate respondsToSelector:@selector(klClient:respSubscribeWithMid:answerSdp:)]) {
                            [ws.delegate klClient:ws respSubscribeWithMid:mid answerSdp:sdp];
                        }
                    }
                }
            }
        }
        
        if ([result.allKeys containsObject:@"notification"]){
            BOOL bResp = [result[@"notification"] boolValue];
            if (bResp && [result.allKeys containsObject:@"method"]) {
                NSString *method = result[@"method"];
                if ([@"peer-join" isEqualToString:method]) {
                    if (ws.delegate && [ws.delegate respondsToSelector:@selector(klClient:respPeerJoinWithData:)]) {
                        [ws.delegate klClient:ws respPeerJoinWithData:result];
                    }
                }
                else if ([@"peer-leave" isEqualToString:method]) {
                    if (ws.delegate && [ws.delegate respondsToSelector:@selector(klClient:respPeerLeaveWithData:)]) {
                        [ws.delegate klClient:ws respPeerLeaveWithData:result];
                    }
                }
                else if ([@"stream-add" isEqualToString:method]) {
                    NSString *mid = result[@"data"][@"mid"] ?: @"";
                    if (ws.delegate && [ws.delegate respondsToSelector:@selector(klClient:respStreamAddWithMid:)]) {
                        [ws.delegate klClient:ws respStreamAddWithMid:mid];
                    }
                }
                else if ([@"stream-remove" isEqualToString:method]) {
                    if ([result.allKeys containsObject:@"data"]) {
                        NSDictionary *jsonObjDict = result[@"data"];
                        NSString *mid = jsonObjDict[@"mid"] ?: @"";
                        if (ws.delegate && [ws.delegate respondsToSelector:@selector(klClient:respStreamRemoveWithMid:data:)]) {
                            [ws.delegate klClient:ws respStreamRemoveWithMid:mid data:result];
                        }
                    }
                }
            }
        }
    };
}

/**状态回调*/
- (void)eventHandleComplete:(void(^)(BOOL))complete
{
    __weak __typeof(self) ws = self;
    _mKLWebSocket.socketConnect = ^(BOOL success) {
        NSDictionary *responeDict = @{@"event":@(1000),@"code": @(success ? 200 : 201),@"mid":@"",@"roomId":@""};
        if (ws.eventHandleBlock) {
            ws.eventHandleBlock(responeDict);
        }
        if (ws.socketStatusBlock) {
            ws.socketStatusBlock(success ? 200 : 201);
        }
        complete(success);
    };
}

#pragma mark - Getter

- (KLWebSocket *)mKLWebSocket
{
    if (!_mKLWebSocket) {
        _mKLWebSocket = [[KLWebSocket alloc] init];
    }
    return _mKLWebSocket;
}

@end
